/*!
 * LMV v6.4.1
 * 
 * Copyright 2019 Autodesk, Inc.
 * All rights reserved.
 * 
 * This computer source code and related instructions and comments are the
 * unpublished confidential and proprietary information of Autodesk, Inc.
 * and are protected under Federal copyright and state trade secret law.
 * They may not be disclosed to, copied or used by any third party without
 * the prior written consent of Autodesk, Inc.
 * 
 * Autodesk Forge Viewer Usage Limitations:
 * 
 * The Autodesk Forge viewer can only be used to view files generated by
 * Autodesk Forge services. The Autodesk Forge Viewer JavaScript must be
 * delivered from an Autodesk hosted URL.
 */
Autodesk.Extensions.ScalarisSimulation =
/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ 		}
/******/ 	};
/******/
/******/ 	// define __esModule on exports
/******/ 	__webpack_require__.r = function(exports) {
/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 		}
/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
/******/ 	};
/******/
/******/ 	// create a fake namespace object
/******/ 	// mode & 1: value is a module id, require it
/******/ 	// mode & 2: merge all properties of value into the ns
/******/ 	// mode & 4: return value when already ns object
/******/ 	// mode & 8|1: behave like require
/******/ 	__webpack_require__.t = function(value, mode) {
/******/ 		if(mode & 1) value = __webpack_require__(value);
/******/ 		if(mode & 8) return value;
/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ 		var ns = Object.create(null);
/******/ 		__webpack_require__.r(ns);
/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ 		return ns;
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = "./extensions/ScalarisSimulation/ScalarisSimulation.js");
/******/ })
/************************************************************************/
/******/ ({

/***/ "./extensions/ScalarisSimulation/ScalarisSimulation.css":
/*!**************************************************************!*\
  !*** ./extensions/ScalarisSimulation/ScalarisSimulation.css ***!
  \**************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {


var content = __webpack_require__(/*! !../../node_modules/css-loader!./ScalarisSimulation.css */ "./node_modules/css-loader/index.js!./extensions/ScalarisSimulation/ScalarisSimulation.css");

if(typeof content === 'string') content = [[module.i, content, '']];

var transform;
var insertInto;



var options = {"hmr":true}

options.transform = transform
options.insertInto = undefined;

var update = __webpack_require__(/*! ../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);

if(content.locals) module.exports = content.locals;

if(false) {}

/***/ }),

/***/ "./extensions/ScalarisSimulation/ScalarisSimulation.js":
/*!*************************************************************!*\
  !*** ./extensions/ScalarisSimulation/ScalarisSimulation.js ***!
  \*************************************************************/
/*! exports provided: ScalarisSimulation */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScalarisSimulation", function() { return ScalarisSimulation; });
/* harmony import */ var _ScalarisSimulation_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ScalarisSimulation.css */ "./extensions/ScalarisSimulation/ScalarisSimulation.css");
/* harmony import */ var _ScalarisSimulation_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_ScalarisSimulation_css__WEBPACK_IMPORTED_MODULE_0__);
 // IMPORTANT!!

/*! @preserve © 2018 Autodesk Inc. All rights reserved */
/*
                                                           * Add/Remove Scalaris Stress Visualization UI to/from the viewer.
                                                           * Toggles the visualization of simulation data in the model.
                                                           */

'use strict';

var av = Autodesk.Viewing;
var avp = av.Private;

var SCALARIS_SIMULATION_EXTENSION_ID = 'Autodesk.Viewing.ScalarisSimulation';
var SCALARIS_SIMULATION_BUTTON_ID = 'toolbar-simulation';

// The legend for factor of safety results defaults to a range of 0–15.
var SCALARIS_FOS_MIN = 0;
var SCALARIS_FOS_MAX = 15;
var SCALARIS_FOS_TARGET = 1;
// The yield strength value for the default physical material AlSi10Mg is 240000000 Pa.
var SCALARIS_YIELD_STRENGTH = 240000000;

// Set the default environment to "Photo Booth". 
av.DefaultSettings.lightPreset = 4;

/**
                                     * Return linear interpolated color.
                                     * https://gist.github.com/rosszurowski/67f04465c424a9bc0dae
                                     * @param {String} a - First color.
                                     * @param {String} b - Second color.
                                     * @param {Number} amount - Amount to interpolate [0, 1].
                                     * @return {String} Interpolated color.
                                     * @private
                                     */
function _lerpColor(a, b, amount) {
  var ah = parseInt(a.replace(/#/g, ''), 16),
  ar = ah >> 16,ag = ah >> 8 & 0xff,ab = ah & 0xff,
  bh = parseInt(b.replace(/#/g, ''), 16),
  br = bh >> 16,bg = bh >> 8 & 0xff,bb = bh & 0xff,
  rr = ar + amount * (br - ar),
  rg = ag + amount * (bg - ag),
  rb = ab + amount * (bb - ab);

  return '#' + ((1 << 24) + (rr << 16) + (rg << 8) + rb | 0).toString(16).slice(1);
}

/**
   * Return interpolated color for a linear gradient given a number of stops.
   * @param {Array<String>} stops - An array of gradient stops.
   * @param {Number} frac - Fraction [0, 1].
   * @return {String} Interpolated color.
   * @private
   */
function _gradient(stops, frac) {
  var numIntervals = stops.length - 1;
  for (var i = 0; i < numIntervals + 1; ++i) {
    if (frac <= (i + 1) / numIntervals) {
      return _lerpColor(stops[i], stops[i + 1], numIntervals * frac - i);
    }
  }
  return null;
}

/**
   * Creates a dom element.
   * @param {String} tagName - Element tag name.
   * @param {String} [className] - Optional class name.
   * @param {String} [textContent] - Optional text content.
   * @param {Array<Element>} [children] - Optional array of children.
   * @return {Element} New element.
   * @private
   */
function _createElement(tagName, className, textContent, children) {
  var elem = document.createElement(tagName);
  if (className) {
    elem.className = className;
  }
  if (textContent) {
    elem.textContent = textContent;
  }
  if (children) {
    for (var i = 0, length = children.length; i < length; ++i) {
      elem.appendChild(children[i]);
    }
  }
  return elem;
}


/**
   * Convert hexadecimal colors to their RGB values.
   * @return {Array<Number>} RGB colors (range 0-1).
   * @private
   */
function _hex_to_RGB(hex) {
  var m = hex.match(/^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i);
  return {
    r: parseInt(m[1], 16) / 255,
    g: parseInt(m[2], 16) / 255,
    b: parseInt(m[3], 16) / 255 };

}

/**
   * Return a color map.
   * @param {Number} nColors - Number of colors.
   * @param {Array<Number>} colors - Array of RGB colors.
   * @param {Array<Number>} percents - Array of color percentages.
   * @param {Array<Number>} ranges - Array of color ranges.
   * @return {Array<Number>} Color map.
   * @private
   */
function _buildColorMap(nColors, colors, percents, ranges) {
  var colorMap = [];
  var nbColors = colors.length;
  if (colors === undefined || !nbColors) {
    return colorMap;
  }
  if (nbColors === 1) {
    for (var i = 0; i < nColors; i++) {
      colorMap[i * 3] = colors[0].r;
      colorMap[i * 3 + 1] = colors[0].g;
      colorMap[i * 3 + 2] = colors[0].b;
    }
  } else {
    var nbBands = nbColors - 1;
    var totalSize = 0;
    for (var b = 0; b < nbBands; b++) {
      var size = Math.floor(nColors * (percents[b] / 100));
      if (b === nbBands - 1) {
        size = nColors - totalSize;
      }
      var sc = b;
      var ec = b + 1;
      var li = b === nbBands - 1 ? nColors - totalSize : size;
      var oset = 3 * totalSize;
      for (var c = 0; c < li; c++) {
        var t = c / li;
        colorMap[oset + 3 * c] = colors[sc].r + t * (colors[ec].r - colors[sc].r);
        colorMap[oset + 3 * c + 1] = colors[sc].g + t * (colors[ec].g - colors[sc].g);
        colorMap[oset + 3 * c + 2] = colors[sc].b + t * (colors[ec].b - colors[sc].b);
      }
      totalSize += size;
      ranges[b] = totalSize - 1;
    }
    colorMap[3 * (nColors - 1)] = colors[nbBands].r;
    colorMap[3 * (nColors - 1) + 1] = colors[nbBands].g;
    colorMap[3 * (nColors - 1) + 2] = colors[nbBands].b;
  }
  return colorMap;
}

/**
   * ScalarisSimulationExtension adds a toggle simulation button 
   * ('Von Mises stress'/'Factor of safety') to settingsTools toolbar.
   * @constructor
   * @see {@link Autodesk.Viewing.Extension} for common inherited methods.
   * @param {Autodesk.Viewing.Viewer3D} viewer - Viewer instance.
   * @param {Object} options - Not used.
   */
function ScalarisSimulationExtension(viewer, options) {
  av.Extension.call(this, viewer, options);

  this._autoShowTooltip = true; // Show tooltip automatically?
  this._ignoreCameraChanged = false; // Should we be (temporarily) ignoring camera changed events?
  this._tooltip = null;
  this._tooltipText = null;
  this._tooltipBar = null;
  this._tooltipArrow = null;
  this._styleSheet = null; // Custom stylesheet for the tooltips
  this._eventClientY = 0; // event.clientY result from current mousemove event
  this._moveAnimationRequestId = null; // Used to debounce mousemove
  this._simulationMode = 'fos';
  this._colorMap = [];
  this._colorRange = [];
  this._skip = false;

  this._onToolbarCreated = this._onToolbarCreated.bind(this);
  this._onGeometryLoaded = this._onGeometryLoaded.bind(this);
  this._onMouseMove = this._onMouseMove.bind(this);
  this._handleMouseMove = this._handleMouseMove.bind(this);
  this._onCameraChanged = this._onCameraChanged.bind(this);
  this._defaultFormatter = this._defaultFormatter.bind(this);

  this._config = {
    formatterVms: this._defaultFormatter,
    unitsVms: 'Pa',
    formatterFos: this._defaultFormatter,
    multiple: false,
    min: null,
    max: null };

}

ScalarisSimulationExtension.prototype = Object.create(av.Extension.prototype);
av.EventDispatcher.prototype.apply(ScalarisSimulationExtension.prototype);
ScalarisSimulationExtension.prototype.constructor = ScalarisSimulationExtension;

ScalarisSimulationExtension.Events = {
  SCALARIS_SIMULATION_MODE_CHANGED: 'Autodesk.Viewing.ScalarisSimulation.Event.ModeChanged' };


/**
                                                                                                * Load the Scalaris simulation extension.
                                                                                                * @override
                                                                                                * @returns {boolean}
                                                                                                */
ScalarisSimulationExtension.prototype.load = function () {
  var viewer = this.viewer;
  var loader = viewer.model.loader;
  var svf = loader.svf;
  if (!loader || !svf) {
    return false;
  }

  if (!(loader instanceof avp.ScalarisLoader)) {
    av.Private.logger.warn('No scalaris loader available for extension', SCALARIS_SIMULATION_EXTENSION_ID);
    return false;
  }

  if (loader.basePath.endsWith('models/')) {
    this._config.min = SCALARIS_FOS_MIN;
    this._config.max = SCALARIS_FOS_MAX;
    viewer.targetFos = SCALARIS_FOS_TARGET;
    viewer.yieldStrength = SCALARIS_YIELD_STRENGTH;
    this._skip = true;
  }

  if (svf.stressData) {
    // Generate the color map.
    var nColors = 256;
    var colors = [];
    var percents = [];
    // Stress reference:
    // High:  [0,FoS target]
    // Ideal: [FoS target,FoS target+2]
    // Low:   [FoS target+2,15+]
    if (viewer.yieldStrength) {
      if (!viewer.targetFos) {
        viewer.targetFos = SCALARIS_FOS_TARGET;
      }
      if (this._config.min === null) {
        this._config.min = SCALARIS_FOS_MIN;
      }
      if (this._config.max === null) {
        this._config.max = SCALARIS_FOS_MAX;
      }
      colors = [_hex_to_RGB('#009BE8'), _hex_to_RGB('#00B50B'), _hex_to_RGB('#00B50B'), _hex_to_RGB('#FC4E4E')];
      percents = [40, 20, 40];
    } else {
      // von Mises Stress:
      // Max: stressMax
      // Min: stressMin
      this._simulationMode = 'vms';
      colors = [_hex_to_RGB('#FC4E4E'), _hex_to_RGB('#00B50B'), _hex_to_RGB('#009BE8')];
      percents = [50, 50];
    }
    this._colorMap = _buildColorMap(nColors, colors, percents, this._colorRange);

    if (viewer.toolbar) {
      this._createUI();
    } else {
      viewer.addEventListener(av.TOOLBAR_CREATED_EVENT, this._onToolbarCreated);
    }

    this._onGeometryLoaded();
    viewer.addEventListener(av.GEOMETRY_LOADED_EVENT, this._onGeometryLoaded);
  }

  // Modify the light preset environment for the viewer.
  var preset = av.Private.LightPresets[av.DefaultSettings.lightPreset];
  preset.E_bias = -1.5;
  preset.tonemap = 1;
  preset.lightMultiplier = 2.2973967099940698;
  // Disable the screen space ambient occlusion.
  viewer.setQualityLevel(false, viewer.impl.renderer().getAntialiasing());
  viewer.impl.setLightPreset(av.DefaultSettings.lightPreset, true);
  // Set the background color.
  viewer.setBackgroundColor(255, 255, 255, 255, 255, 255);

  return true;
};

/**
    * Unload the Scalaris simulation extension.
    * @override
    * @returns {boolean}
    */
ScalarisSimulationExtension.prototype.unload = function () {
  // Disable display of simulation data.
  this.setDisplayResult(false);

  // Remove the simulation UI from the viewer.
  if (this._legendContainer) {
    this.viewer.container.removeChild(this._legendContainer);
    // Remove a control from this control group.
    this.viewer.settingsTools.removeControl(SCALARIS_SIMULATION_BUTTON_ID);
  }

  this.viewer.removeEventListener(av.GEOMETRY_LOADED_EVENT, this._onGeometryLoaded);

  return true;
};

/**
    * Toggle the display of simulation result on the model and related UI in the viewer.
    * @param {boolean} show - enables or disables the display.
    */
ScalarisSimulationExtension.prototype.setDisplayResult = function (show) {
  var defMaterial = this.viewer.impl.getMaterials().defaultMaterial;
  if (!defMaterial) {
    return;
  }

  if (this._legendContainer) {
    this._legendContainer.hidden = !show;
  }

  if (this._simulationButton) {
    if (show) {
      this._simulationButton.setIcon('adsk-toolbar-view-modelIcon');
      this._simulationButton.setToolTip(av.i18n.translate('Model View'));
    } else {
      this._simulationButton.setIcon('adsk-toolbar-view-stress-referenceIcon');
      if (!this.viewer.yieldStrength) {
        this._simulationButton.setToolTip(av.i18n.translate('Von Mises stress'));
      } else {
        this._simulationButton.setToolTip(av.i18n.translate('Stress View'));
      }
    }
  }

  // If we're turning on the stress display and auto-show-tooltip is enabled,
  // then we need to update the contents of the tooltip.
  if (show && this._autoShowTooltip) {
    this.viewer.addEventListener(av.CAMERA_CHANGE_EVENT, this._onCameraChanged);
    this._handleMouseMove();
  }

  defMaterial.vertexColors = show ? THREE.VertexColors : THREE.NoColors;
  defMaterial.needsUpdate = true;
  this.viewer.impl.invalidate(true, true, false); // trigger re-render
};

/**
    * Set the range and generate the color vertices for the mesh from the simulation data.
    * @param {number} [min] - minimum von Mises stress/factor of safety value.
    * @param {number} [max] - maximum von Mises stress/factor of safety value.
    */
ScalarisSimulationExtension.prototype.setRange = function (min, max) {
  if (this._skip) {
    return;
  }

  var viewer = this.viewer;
  var geometry = viewer.model.getGeometryList().geoms[1];
  if (!geometry) {
    return;
  }

  var svf = viewer.model.loader.svf;
  var stressData = svf.stressData;
  if (!stressData) {
    return;
  }

  var stressCount = stressData.length;
  if (!stressCount) {
    return;
  }

  var nbColors = this._colorMap.length / 3;
  if (nbColors === 0) {
    return;
  }

  if (min === undefined) {
    min = svf.stressMin;
  }
  if (max === undefined) {
    max = svf.stressMax;
  }

  if (min === max) {
    return;
  }

  var colorScale, colorIndex;
  var vertexColors = new Float32Array(stressCount * 3);
  if (this._simulationMode === 'vms') {
    var sRange = max - min;
    for (var i = 0; i < stressCount; i++) {
      colorScale = (stressData[i] - min) / sRange;
      colorIndex = Math.floor((1 - colorScale) * (nbColors - 1));
      vertexColors[i * 3] = this._colorMap[colorIndex * 3];
      vertexColors[i * 3 + 1] = this._colorMap[colorIndex * 3 + 1];
      vertexColors[i * 3 + 2] = this._colorMap[colorIndex * 3 + 2];
    }
  } else if (this._simulationMode === 'fos') {
    var color;
    var maxFos = SCALARIS_FOS_MAX;
    var maxTargetFos = viewer.targetFos + 2;
    if (maxTargetFos > SCALARIS_FOS_MAX) {
      maxFos = viewer.targetFos * 2;
    }
    if (viewer.yieldStrength) {
      min = viewer.yieldStrength / svf.stressMax;
      max = viewer.yieldStrength / svf.stressMin;
    }
    if (!isFinite(min) || isNaN(min)) {
      min = SCALARIS_FOS_MIN;
    }
    if (!isFinite(max) || isNaN(max) || max > maxFos) {
      max = maxFos;
    }
    if (min >= SCALARIS_FOS_MAX || max < 1 || min >= viewer.targetFos && max <= maxTargetFos) {
      if (min >= SCALARIS_FOS_MAX) {
        color = _hex_to_RGB('#009BE8'); // blue
      } else if (max < 1) {
        color = _hex_to_RGB('#FC4E4E'); // red
      } else {
        color = _hex_to_RGB('#00B50B'); // green
      }
      for (var i = 0; i < stressCount; i++) {
        vertexColors[i * 3] = color.r;
        vertexColors[i * 3 + 1] = color.g;
        vertexColors[i * 3 + 2] = color.b;
      }
    } else {
      var fosMin = Infinity,fosMax = -Infinity;
      if (min > max) {
        min = [max, max = min][0];
      }
      if (min < fosMin) {
        fosMin = min;
      }
      if (max > fosMax) {
        fosMax = max;
      }
      color = _hex_to_RGB('#00B50B'); // green
      for (var i = 0; i < stressCount; i++) {
        var fos;
        if (viewer.yieldStrength) {
          fos = viewer.yieldStrength / stressData[i];
        }
        if (!isFinite(fos) || fos > maxFos) {
          fos = maxFos;
        } else if (isNaN(fos)) {
          fos = SCALARIS_FOS_MIN;
        }
        if (fos >= viewer.targetFos && fos <= maxTargetFos) {
          // FoS in [target FoS, target FoS+2] is mapped to green (00B50B).
          vertexColors[i * 3] = color.r;
          vertexColors[i * 3 + 1] = color.g;
          vertexColors[i * 3 + 2] = color.b;
        } else {
          if (fos < viewer.targetFos) {
            // FoS mapped from red to green.
            var size = this._colorRange[2] - this._colorRange[1];
            var d1 = Math.abs(fos - viewer.targetFos);
            var d2 = Math.abs(fosMin - viewer.targetFos);
            colorScale = this._colorRange[1] + d1 * size / d2;
            colorIndex = Math.floor(colorScale);
            if (colorIndex > this._colorRange[2]) {
              colorIndex = this._colorRange[2];
            }
          } else if (fos > maxTargetFos) {
            // FoS mapped from green to blue.
            var size = this._colorRange[0];
            var d1 = Math.abs(fos - viewer.targetFos - 2);
            var d2 = Math.abs(fosMax - viewer.targetFos - 2);
            colorScale = d1 * size / d2;
            colorIndex = size - Math.floor(colorScale);
            if (colorIndex < 0) {
              colorIndex = 0;
            }
          }
          vertexColors[i * 3] = this._colorMap[colorIndex * 3];
          vertexColors[i * 3 + 1] = this._colorMap[colorIndex * 3 + 1];
          vertexColors[i * 3 + 2] = this._colorMap[colorIndex * 3 + 2];
        }
      }
    }
  }

  if (vertexColors && vertexColors.byteLength) {
    geometry.addAttribute('color', new THREE.BufferAttribute(new Float32Array(vertexColors), 3));
    geometry.hasColors = true;
    geometry.colorsNeedUpdate = true;
  }
};

/**
    * Set configuration for this extension.
    * @param {Object} config - Configuration.
    */
ScalarisSimulationExtension.prototype.setConfiguration = function (config) {
  var configExt = this._config;
  configExt = Object.assign(configExt, config || {});

  if (!configExt.formatterVms) {
    configExt.formatterVms = this._defaultFormatter;
  }
  if (!configExt.unitsVms) {
    configExt.unitsVms = 'Pa';
  }
  if (!configExt.formatterFos) {
    configExt.formatterFos = this._defaultFormatter;
  }
  if (config.formatterVms || config.formatterFos || config.min || config.max || config.unitsVms) {
    if (this._simulationMode === 'vms' && config.unitsVms) {
      var title = this._legendContainer.getElementsByClassName('adsk-legend-title');
      title[0].textContent = av.i18n.translate('Units Stress', { units: config.unitsVms });
    } else if (this._simulationMode === 'fos') {
      this.setRange(SCALARIS_FOS_MIN, SCALARIS_FOS_MAX);
    }
    this.forceLegendUpdate();
  }
};

/**
    * Set the simulation mode for this extension.
    * @param {String} mode - Simulation mode (should be 'vms' or 'fos').
    */
ScalarisSimulationExtension.prototype.setSimulationMode = function (mode) {
  this._simulationMode = mode;
};

/**
    * Return the simulation mode for this extension.
    * @return {String} - Returns the simulation mode.
    */
ScalarisSimulationExtension.prototype.getSimulationMode = function () {
  return this._simulationMode;
};

/**
    * Forces an update of the legend.
    */
ScalarisSimulationExtension.prototype.forceLegendUpdate = function () {
  this._setLegendLabels();
  this._handleMouseMove();
};

/**
    * Creates the legend min/max labels.
    * @private
    */
ScalarisSimulationExtension.prototype._setLegendLabels = function () {
  if (this._simulationMode === 'vms') {
    this._minTitle.textContent = av.i18n.translate('Min');
    this._maxTitle.textContent = av.i18n.translate('Max');
  } else if (this._simulationMode === 'fos') {
    this._minTitle.textContent = av.i18n.translate('Low');
    this._midTitle.textContent = av.i18n.translate('Ideal');
    this._maxTitle.textContent = av.i18n.translate('High');
  }
};

/**
    * Default numeric value formatter.
    * @param {Number} value - Value to format.
    * @private
    */
ScalarisSimulationExtension.prototype._defaultFormatter = function (value) {
  if (this._simulationMode === 'vms') {
    return Number.isFinite(Number(value)) ? Number.parseFloat(value).toExponential(2) : value.toString();
  }
  return value.toString();
};

/**
    * @private
    * Remove the toolbar creation event listener and create the UI elements for simulation data.
    */
ScalarisSimulationExtension.prototype._onToolbarCreated = function () {
  this.viewer.removeEventListener(av.TOOLBAR_CREATED_EVENT, this._onToolbarCreated);
  this._createUI();
};

/**
    * Callback when the geometry is loaded.
    */
ScalarisSimulationExtension.prototype._onGeometryLoaded = function () {
  this.setRange();
  this._setLegendLabels();

  var isResultVisible = this._legendContainer && !this._legendContainer.hidden;
  this.setDisplayResult(isResultVisible);
  if (isResultVisible && this._autoShowTooltip) {

    // As a result of loadModel(), the listener setup in setDisplayResult() will see some
    // camera changed events. For the purposes of hiding the tooltip, we need to ignore
    // those. Wait for a while until the display stabilizes.
    this._ignoreCameraChanged = true;

    var that = this;
    setTimeout(function () {
      that._ignoreCameraChanged = false;
      that.viewer.addEventListener(av.CAMERA_CHANGE_EVENT, that._onCameraChanged);
    }, 500);
  }
};

/**
    * Handler for camera changed event.
    * Turn off auto-show-tooltip and remove this listener.
    * @private
    */
ScalarisSimulationExtension.prototype._onCameraChanged = function () {
  if (this._ignoreCameraChanged) {
    return;
  }

  if (this._autoShowTooltip) {
    this._tooltip.classList.remove('adsk-legend-tooltip-active');
    this._autoShowTooltip = false;
  }

  this.viewer.removeEventListener(av.CAMERA_CHANGE_EVENT, this._onCameraChanged);
};

/**
    * Handler for mousemove events in the legend.
    * @param {Event} event - Mouse event.
    * @private
    */
ScalarisSimulationExtension.prototype._onMouseMove = function (event) {
  this._eventClientY = event.clientY;

  if (this._autoShowTooltip) {
    this._tooltip.classList.remove('adsk-legend-tooltip-active');
    this._autoShowTooltip = false;
  }

  // Debounce.
  if (!this._moveAnimationRequestId) {
    this._moveAnimationRequestId = requestAnimationFrame(this._handleMouseMove);
  }
};

/**
    * Handler called (via requestAnimationFrame) on mousemove events.
    * @private
    */
ScalarisSimulationExtension.prototype._handleMouseMove = function () {
  this._moveAnimationRequestId = null;

  if (!this._colorScale) {
    return; // No color scale = no legend = shouldn't be trying to display a tooltip
  }

  // Position the tooltip to match the cursor position.
  var rect = this._colorScale.getBoundingClientRect();
  var height = rect.height;
  if (!height) {
    return; // Zero height = legend hasn't been sized yet = don't update tooltip.
  }

  var top = rect.top;
  var bottom = rect.bottom;
  var y = Math.min(Math.max(0, this._eventClientY - top), height);

  // If we're within some margin of the min/max, then clamp.
  var atMax = false;
  var atMin = false;

  if (Math.abs(top - this._eventClientY) < 8) {
    y = 0;
    atMax = true;
  }

  if (Math.abs(bottom - this._eventClientY) < 8) {
    y = height;
    atMin = true;
  }

  // If auto-show-tooltip is enabled, then put the tooltip in the middle;
  if (this._autoShowTooltip) {
    y = height / 2;
    atMax = false;
    atMin = false;
  }

  var config = this._config;
  // Why this tweak to the position?
  this._tooltip.style.top = (config.multiple ? y : y + 7) + 'px';

  // Grab the min/max stress/fos values from the file or the legend config.
  var svf = this.viewer.model.loader.svf;
  var stressMin = config.min != null ? config.min : svf.stressMin;
  var stressMax = config.max != null ? config.max : svf.stressMax;
  var frac = y / height;
  if (this._simulationMode === 'vms') {
    frac = 1 - frac;
  }
  var value = stressMin + (stressMax - stressMin) * frac;

  // Build the html for the tooltip.
  function createSpan(className, textContent) {
    return _createElement('span', className, textContent);
  }

  function createBR() {
    return _createElement('br');
  }

  var content = [];
  var className, textContent;
  var status, statusText;
  if (this._simulationMode === 'vms') {
    if (!this.viewer.yieldStrength) {
      content.push(createSpan('adsk-legend-tooltip-title', av.i18n.translate('Von Mises stress')));
    } else {
      content.push(createSpan('adsk-legend-tooltip-title', av.i18n.translate('Stress reference')));
    }
  } else if (this._simulationMode === 'fos') {
    // The indicator shows 3 possible states of the current design study: low, ideal and high.
    // These states are based on the lowest resultant safety factor in the design and the
    // default or user-specified safety factor targets.
    if (value > 9) {
      status = 'Low Stress';
      statusText = 'Stress in these regions is lower than required';
    } else if (value >= 6 && value <= 9) {
      status = 'Ideal Stress';
      statusText = 'Stress in these regions is the most performant';
    } else if (value < 6) {
      status = 'High Stress';
      statusText = 'Stress in these regions should be noted and may require attention';
    }
    content.push(createSpan('adsk-legend-tooltip-title', av.i18n.translate('Stress Status', { status: status })));
  }
  content.push(createBR());

  /*
                            if (config.multiple) {
                              content.push(createSpan('adsk-legend-tooltip-subtitle', av.i18n.translate('For all displayed outcomes')));
                              content.push(createBR());
                            }
                            */
  content.push(createBR());

  className = 'adsk-legend-tooltip-value';
  textContent = this._simulationMode === 'vms' ? config.formatterVms(stressMax) : undefined;
  if (atMax) {
    className += ' adsk-legend-tooltip-highlight';
    if (this._simulationMode === 'vms') {
      textContent = av.i18n.translate('Max Value', { max: textContent });
      content.push(createSpan(className, textContent));
    }
  }

  if (!atMax && !atMin && this._simulationMode === 'vms') {
    content.push(createSpan('adsk-legend-tooltip-value adsk-legend-tooltip-highlight', config.formatterVms(value)));
  }

  className = 'adsk-legend-tooltip-value';
  if (this._simulationMode === 'vms') {
    textContent = config.formatterVms(stressMin);
  } else if (this._simulationMode === 'fos') {
    textContent = this._defaultFormatter(stressMin.toFixed(2));
  }

  textContent = this._simulationMode === 'vms' ? config.formatterVms(stressMin) : undefined;
  if (atMin) {
    className += ' adsk-legend-tooltip-highlight';
    if (this._simulationMode === 'vms') {
      textContent = av.i18n.translate('Min Value', { min: textContent });
      content.push(createSpan(className, textContent));
    }
  }

  className = 'adsk-legend-tooltip-value';
  if (this._simulationMode === 'fos') {
    content.push(createSpan(className, av.i18n.translate('Stress Text', { statusText: statusText })));
    content.push(createBR());
  }

  var node = this._tooltipText;
  while (node.hasChildNodes()) {
    node.removeChild(node.lastChild);
  }
  for (var i = 0, length = content.length; i < length; ++i) {
    node.appendChild(content[i]);
  }

  // Set color to match the legend's color scale (emulate the css linear-gradient).
  var color;
  if (this._simulationMode === 'vms') {
    color = _gradient(['#009BE8', '#00B50B', '#FC4E4E'], frac);
  } else if (this._simulationMode === 'fos') {
    color = _gradient(['#009BE8', '#00B50B', '#FC4E4E'], 1 - frac);
  }
  if (color) {
    this._tooltipBar.style.background = color;
    if (this._styleSheet.cssRules.length) {
      this._styleSheet.deleteRule(0);
    }
    this._styleSheet.insertRule('.adsk-legend-tooltip-arrow::after {border-left-color:' + color + '}', 0);
  }
};

/**
    * @private
    * Create the UI elements (legend and simulation button) for displaying simulation results.
    */
ScalarisSimulationExtension.prototype._createUI = function () {
  var viewer = this.viewer;
  var svf = viewer.model.loader.svf;
  var loadOptions = svf.loadOptions;
  var settingsTools = viewer.settingsTools;
  if (loadOptions) {
    var scalarisFile = loadOptions.defaultFileType || loadOptions.svf.slice(loadOptions.svf.length - 8).toLowerCase();
    if (scalarisFile === 'scalaris' && svf.stressData && svf.stressData.byteLength) {

      // Add the simulation UI to the viewer .
      this._legendContainer = document.createElement('div');
      this._legendContainer.classList.add('adsk-legend-container');
      var title = document.createElement('div');
      if (!viewer.yieldStrength) {
        title.textContent = av.i18n.translate('Von Mises stress (Pa)');
      } else {
        title.textContent = av.i18n.translate('Stress reference');
      }
      title.classList.add('adsk-legend-title');
      var scaleContainer = document.createElement('div');
      scaleContainer.classList.add('adsk-legend-scale-container');
      this._colorScale = document.createElement('div');
      this._colorScale.classList.add('adsk-legend-color-scale');
      var labelContainer = document.createElement('div');
      labelContainer.classList.add('adsk-legend-label-container');
      this._maxLabel = document.createElement('div');
      this._maxLabel.classList.add('adsk-legend-max-label');
      this._minLabel = document.createElement('div');
      this._minLabel.classList.add('adsk-legend-min-label');
      var titleContainer = document.createElement('div');
      titleContainer.classList.add('adsk-legend-title-container');
      this._maxTitle = document.createElement('div');
      this._maxTitle.classList.add('adsk-legend-max-title');
      this._midTitle = document.createElement('div');
      this._midTitle.classList.add('adsk-legend-mid-title');
      this._minTitle = document.createElement('div');
      this._minTitle.classList.add('adsk-legend-min-title');

      this._createTooltip(this._colorScale);

      var titleTooltip = document.createElement('div');
      titleTooltip.classList.add('adsk-legend-title-tooltip');
      if (!viewer.yieldStrength) {
        titleTooltip.textContent = av.i18n.translate('Displays the distribution of von Mises stress on the surface of the generated outcome.');
      } else {
        titleTooltip.textContent = av.i18n.translate('Displays the distribution of stress based on the factor of safety value set in the Objectives and Limits dialog in the Define workspace.');
      }
      title.appendChild(titleTooltip);
      labelContainer.appendChild(this._maxLabel);
      labelContainer.appendChild(this._minLabel);
      titleContainer.appendChild(this._maxTitle);
      titleContainer.appendChild(this._midTitle);
      titleContainer.appendChild(this._minTitle);
      scaleContainer.appendChild(labelContainer);
      scaleContainer.appendChild(this._colorScale);
      scaleContainer.appendChild(titleContainer);
      this._legendContainer.appendChild(title);
      this._legendContainer.appendChild(scaleContainer);
      viewer.container.insertBefore(this._legendContainer, viewer.viewCubeUi.container);

      this._simulationButton = new av.UI.Button(SCALARIS_SIMULATION_BUTTON_ID);
      if (!viewer.yieldStrength) {
        this._simulationButton.setToolTip(av.i18n.translate('Von Mises stress'));
      } else {
        this._simulationButton.setToolTip(av.i18n.translate('Stress View'));
      }

      this._simulationButton.setIcon('adsk-toolbar-view-stress-referenceIcon');
      var scope = this;
      this._simulationButton.onClick = function () {
        if (scope._legendContainer) {
          scope.setDisplayResult(scope._legendContainer.hidden);
        }
      };

      settingsTools.addControl(this._simulationButton, { index: viewer.settingsTools.getNumberOfControls() });
    } else {
      av.Private.logger.warn('No simulation data available to view for extension', SCALARIS_SIMULATION_EXTENSION_ID);
    }
    this.setDisplayResult(false);
  }
};

/**
    * Creates the legend tooltip (popover) ui.
    * @param {Element} parent - Parent element.
    * @private
    */
ScalarisSimulationExtension.prototype._createTooltip = function (parent) {
  function createDiv(className, children) {
    return _createElement('div', className, null, children);
  }

  // Create the html.
  this._tooltipArrow = createDiv('adsk-legend-tooltip-arrow');
  this._tooltipBar = createDiv('adsk-legend-tooltip-bar');
  this._tooltipText = createDiv('adsk-legend-tooltip-text');
  this._tooltip = createDiv('adsk-legend-tooltip', [
  createDiv('adsk-legend-tooltip-box', [this._tooltipText, this._tooltipBar]),
  this._tooltipArrow]);


  if (this._autoShowTooltip) {
    this._tooltip.classList.add('adsk-legend-tooltip-active');
  }
  this._tooltip.style.top = '0';

  // Add the tooltip to the parent and add a mousemove event handler.
  parent.appendChild(this._tooltip);
  parent.onmousemove = this._onMouseMove;

  // Create a custom stylesheet, we'll use this for coloring the pseudo-element arrow.
  var style = document.createElement('style');
  style.appendChild(document.createTextNode('')); // webkit hack: still required?
  document.head.appendChild(style);
  this._styleSheet = style.sheet;
};

var ScalarisSimulation = ScalarisSimulationExtension;

/*
                                                              * Register the 'Autodesk.Viewing.ScalarisSimulation' extension with the extension manager.
                                                              */
av.theExtensionManager.registerExtension(SCALARIS_SIMULATION_EXTENSION_ID, ScalarisSimulationExtension);

/***/ }),

/***/ "./node_modules/css-loader/index.js!./extensions/ScalarisSimulation/ScalarisSimulation.css":
/*!****************************************************************************************!*\
  !*** ./node_modules/css-loader!./extensions/ScalarisSimulation/ScalarisSimulation.css ***!
  \****************************************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

exports = module.exports = __webpack_require__(/*! ../../node_modules/css-loader/lib/css-base.js */ "./node_modules/css-loader/lib/css-base.js")(false);
// imports


// module
exports.push([module.i, "/*! © 2018 Autodesk Inc. All rights reserved */\r\n.adsk-legend-container {\r\n  top: 370px;\r\n  right: 20px;\r\n  height: calc(100% - 400px);\r\n  position: absolute;\r\n  min-height: 100px;\r\n}\r\n\r\n.adsk-legend-title {\r\n  height: 20px;\r\n  font-size: 12px;\r\n  font-weight: bold;\r\n  color: #0c0e10;\r\n}\r\n\r\n.adsk-legend-title:hover > .adsk-legend-title-tooltip {\r\n  display: block;\r\n}\r\n\r\n.adsk-legend-title-tooltip {\r\n  width: 200px;\r\n  position: absolute;\r\n  right: 0;\r\n  border-radius: 3px;\r\n  padding: 4px;\r\n  text-align: left;\r\n  font-size: 11px;\r\n  font-weight: initial;\r\n  line-height: 1.2;\r\n  box-shadow: 0 1px 3px rgba(0,0,0,.3);\r\n  transform: translate(0, calc(-100% - 20px));\r\n  color: #f4f4f4;\r\n  background: #4a4a4a;\r\n  display: none;\r\n}\r\n\r\n.adsk-legend-scale-container {\r\n  position: relative;\r\n  height: calc(100% - 80px);\r\n  margin-left: 36px;\r\n}\r\n\r\n.adsk-legend-container.fos-enabled .adsk-legend-color-scale {\r\n  background: linear-gradient(to bottom, #009BE8, #00B50B, #FC4E4E);\r\n  margin: 0 11px 0 4px;\r\n}\r\n\r\n.adsk-legend-container.fos-enabled .adsk-legend-max-label {\r\n  color: #009BE8;\r\n}\r\n\r\n.adsk-legend-container.fos-enabled .adsk-legend-min-label {\r\n  color: #FC4E4E;\r\n}\r\n\r\n.adsk-legend-color-scale {\r\n  position: relative;\r\n  display: inline-block;\r\n  background: linear-gradient(to bottom, #FC4E4E, #00B50B, #009BE8);\r\n  width: 20px;\r\n  height: calc(100% + 6px);\r\n}\r\n\r\n.adsk-legend-tooltip {\r\n  display: none;\r\n  position: absolute;\r\n  right: 28px;\r\n  transform: translate(0, calc(-60%));\r\n  pointer-events: none;\r\n  border: 1px solid #9B9B9B;\r\n  border-radius: 4px;\r\n  width: 152px;\r\n}\r\n\r\n.adsk-legend-tooltip-box {\r\n  flex-grow: 1;\r\n  display: flex;\r\n  overflow: hidden;\r\n}\r\n\r\n.adsk-legend-tooltip-min-fos {\r\n  font-size: 14px;\r\n  right: 30px;\r\n}\r\n\r\n.adsk-legend-tooltip-text {\r\n  flex-grow: 1;\r\n  padding: 10px;\r\n  background-color: #9B9B9B;\r\n  color: #FFFFFF;\r\n  font-size: 11px;\r\n}\r\n\r\n.adsk-legend-tooltip-title {\r\n  font-size: 16px;\r\n}\r\n\r\n.adsk-legend-tooltip-highlight {\r\n  color: #FFFFFF;\r\n  font-size: 20px;\r\n}\r\n\r\n.adsk-legend-tooltip-value {\r\n  line-height: 1.5;\r\n}\r\n\r\n.adsk-legend-tooltip-bar {\r\n  width: 10px;\r\n  flex-shrink: 0;\r\n  background-color: black;\r\n}\r\n\r\n.adsk-legend-tooltip-arrow {\r\n  display: inline-block;\r\n  position: relative;\r\n}\r\n\r\n.adsk-legend-tooltip-arrow:after,\r\n.adsk-legend-tooltip-arrow:before {\r\n  content: '';\r\n  display: block;\r\n  position: absolute;\r\n  left: 100%;\r\n  width: 0;\r\n  height: 0;\r\n  border-style: solid;\r\n}\r\n\r\n.adsk-legend-tooltip-arrow:after {\r\n  border-color: transparent transparent transparent red;\r\n  border-width: 8px;\r\n  top: 50%;\r\n  margin-top: -8px;\r\n}\r\n\r\n.adsk-legend-tooltip-arrow:before {\r\n  border-color: transparent transparent transparent #9B9B9B;\r\n  border-width: 9px;\r\n  top: 50%;\r\n  margin-top: -9px;\r\n}\r\n\r\n.adsk-legend-color-scale:hover .adsk-legend-tooltip {\r\n  display: flex;\r\n}\r\n\r\n.adsk-legend-tooltip.adsk-legend-tooltip-active {\r\n  display: flex;\r\n}\r\n\r\n.adsk-legend-label-container {\r\n  display: inline-block;\r\n  height: 100%;\r\n  position: relative;\r\n}\r\n\r\n.adsk-legend-min-label {\r\n  text-align: right;\r\n  font-size: 14px;\r\n  white-space: nowrap;\r\n  color: #009BE8;\r\n}\r\n\r\n.adsk-legend-max-label {\r\n  height: calc(100% - 20px);\r\n  text-align: right;\r\n  font-size: 14px;\r\n  white-space: nowrap;\r\n  color: #FC4E4E;\r\n}\r\n\r\n.adsk-legend-title-container {\r\n  display: inline-block;\r\n  height: 100%;\r\n  position: relative;\r\n}\r\n\r\n.adsk-legend-min-title {\r\n  margin-left: 5px;\r\n  font-size: 14px;\r\n  color: #009BE8;\r\n}\r\n\r\n.adsk-legend-mid-title {\r\n  height: calc(50%);\r\n  margin-left: 5px;\r\n  font-size: 14px;\r\n  color: #00B50B;\r\n}\r\n\r\n.adsk-legend-max-title {\r\n  height: calc(50%);\r\n  margin-left: 5px;\r\n  font-size: 14px;\r\n  color: #FC4E4E;\r\n}\r\n\r\n.adsk-legend-container.fos-enabled .adsk-legend-max-title {\r\n  visibility: hidden;\r\n}\r\n\r\n.adsk-legend-container.fos-enabled .adsk-legend-mid-title {\r\n  visibility: hidden;\r\n}\r\n\r\n.adsk-legend-container.fos-enabled .adsk-legend-min-title {\r\n  visibility: hidden;\r\n}\r\n\r\n.adsk-toolbar-view-modelIcon {\r\n    background-image: url('');\r\n}\r\n\r\n.adsk-toolbar-analysis-displayIcon {\r\n    background-image: url('');\r\n}\r\n\r\n.adsk-toolbar-view-stressIcon {\r\n    background-image: url('');\r\n}\r\n\r\n.adsk-toolbar-view-fosIcon {\r\n    background-image: url('');\r\n}\r\n\r\n.adsk-toolbar-view-stress-referenceIcon {\r\n    background-image: url('');\r\n}", ""]);

// exports


/***/ }),

/***/ "./node_modules/css-loader/lib/css-base.js":
/*!*************************************************!*\
  !*** ./node_modules/css-loader/lib/css-base.js ***!
  \*************************************************/
/*! no static exports found */
/***/ (function(module, exports) {

/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
// css base code, injected by the css-loader
module.exports = function(useSourceMap) {
	var list = [];

	// return the list of modules as css string
	list.toString = function toString() {
		return this.map(function (item) {
			var content = cssWithMappingToString(item, useSourceMap);
			if(item[2]) {
				return "@media " + item[2] + "{" + content + "}";
			} else {
				return content;
			}
		}).join("");
	};

	// import a list of modules into the list
	list.i = function(modules, mediaQuery) {
		if(typeof modules === "string")
			modules = [[null, modules, ""]];
		var alreadyImportedModules = {};
		for(var i = 0; i < this.length; i++) {
			var id = this[i][0];
			if(typeof id === "number")
				alreadyImportedModules[id] = true;
		}
		for(i = 0; i < modules.length; i++) {
			var item = modules[i];
			// skip already imported module
			// this implementation is not 100% perfect for weird media query combinations
			//  when a module is imported multiple times with different media queries.
			//  I hope this will never occur (Hey this way we have smaller bundles)
			if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
				if(mediaQuery && !item[2]) {
					item[2] = mediaQuery;
				} else if(mediaQuery) {
					item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
				}
				list.push(item);
			}
		}
	};
	return list;
};

function cssWithMappingToString(item, useSourceMap) {
	var content = item[1] || '';
	var cssMapping = item[3];
	if (!cssMapping) {
		return content;
	}

	if (useSourceMap && typeof btoa === 'function') {
		var sourceMapping = toComment(cssMapping);
		var sourceURLs = cssMapping.sources.map(function (source) {
			return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'
		});

		return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
	}

	return [content].join('\n');
}

// Adapted from convert-source-map (MIT)
function toComment(sourceMap) {
	// eslint-disable-next-line no-undef
	var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
	var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;

	return '/*# ' + data + ' */';
}


/***/ }),

/***/ "./node_modules/style-loader/lib/addStyles.js":
/*!****************************************************!*\
  !*** ./node_modules/style-loader/lib/addStyles.js ***!
  \****************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

var stylesInDom = {};

var	memoize = function (fn) {
	var memo;

	return function () {
		if (typeof memo === "undefined") memo = fn.apply(this, arguments);
		return memo;
	};
};

var isOldIE = memoize(function () {
	// Test for IE <= 9 as proposed by Browserhacks
	// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
	// Tests for existence of standard globals is to allow style-loader
	// to operate correctly into non-standard environments
	// @see https://github.com/webpack-contrib/style-loader/issues/177
	return window && document && document.all && !window.atob;
});

var getTarget = function (target, parent) {
  if (parent){
    return parent.querySelector(target);
  }
  return document.querySelector(target);
};

var getElement = (function (fn) {
	var memo = {};

	return function(target, parent) {
                // If passing function in options, then use it for resolve "head" element.
                // Useful for Shadow Root style i.e
                // {
                //   insertInto: function () { return document.querySelector("#foo").shadowRoot }
                // }
                if (typeof target === 'function') {
                        return target();
                }
                if (typeof memo[target] === "undefined") {
			var styleTarget = getTarget.call(this, target, parent);
			// Special case to return head of iframe instead of iframe itself
			if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {
				try {
					// This will throw an exception if access to iframe is blocked
					// due to cross-origin restrictions
					styleTarget = styleTarget.contentDocument.head;
				} catch(e) {
					styleTarget = null;
				}
			}
			memo[target] = styleTarget;
		}
		return memo[target]
	};
})();

var singleton = null;
var	singletonCounter = 0;
var	stylesInsertedAtTop = [];

var	fixUrls = __webpack_require__(/*! ./urls */ "./node_modules/style-loader/lib/urls.js");

module.exports = function(list, options) {
	if (typeof DEBUG !== "undefined" && DEBUG) {
		if (typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
	}

	options = options || {};

	options.attrs = typeof options.attrs === "object" ? options.attrs : {};

	// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
	// tags it will allow on a page
	if (!options.singleton && typeof options.singleton !== "boolean") options.singleton = isOldIE();

	// By default, add <style> tags to the <head> element
        if (!options.insertInto) options.insertInto = "head";

	// By default, add <style> tags to the bottom of the target
	if (!options.insertAt) options.insertAt = "bottom";

	var styles = listToStyles(list, options);

	addStylesToDom(styles, options);

	return function update (newList) {
		var mayRemove = [];

		for (var i = 0; i < styles.length; i++) {
			var item = styles[i];
			var domStyle = stylesInDom[item.id];

			domStyle.refs--;
			mayRemove.push(domStyle);
		}

		if(newList) {
			var newStyles = listToStyles(newList, options);
			addStylesToDom(newStyles, options);
		}

		for (var i = 0; i < mayRemove.length; i++) {
			var domStyle = mayRemove[i];

			if(domStyle.refs === 0) {
				for (var j = 0; j < domStyle.parts.length; j++) domStyle.parts[j]();

				delete stylesInDom[domStyle.id];
			}
		}
	};
};

function addStylesToDom (styles, options) {
	for (var i = 0; i < styles.length; i++) {
		var item = styles[i];
		var domStyle = stylesInDom[item.id];

		if(domStyle) {
			domStyle.refs++;

			for(var j = 0; j < domStyle.parts.length; j++) {
				domStyle.parts[j](item.parts[j]);
			}

			for(; j < item.parts.length; j++) {
				domStyle.parts.push(addStyle(item.parts[j], options));
			}
		} else {
			var parts = [];

			for(var j = 0; j < item.parts.length; j++) {
				parts.push(addStyle(item.parts[j], options));
			}

			stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
		}
	}
}

function listToStyles (list, options) {
	var styles = [];
	var newStyles = {};

	for (var i = 0; i < list.length; i++) {
		var item = list[i];
		var id = options.base ? item[0] + options.base : item[0];
		var css = item[1];
		var media = item[2];
		var sourceMap = item[3];
		var part = {css: css, media: media, sourceMap: sourceMap};

		if(!newStyles[id]) styles.push(newStyles[id] = {id: id, parts: [part]});
		else newStyles[id].parts.push(part);
	}

	return styles;
}

function insertStyleElement (options, style) {
	var target = getElement(options.insertInto)

	if (!target) {
		throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");
	}

	var lastStyleElementInsertedAtTop = stylesInsertedAtTop[stylesInsertedAtTop.length - 1];

	if (options.insertAt === "top") {
		if (!lastStyleElementInsertedAtTop) {
			target.insertBefore(style, target.firstChild);
		} else if (lastStyleElementInsertedAtTop.nextSibling) {
			target.insertBefore(style, lastStyleElementInsertedAtTop.nextSibling);
		} else {
			target.appendChild(style);
		}
		stylesInsertedAtTop.push(style);
	} else if (options.insertAt === "bottom") {
		target.appendChild(style);
	} else if (typeof options.insertAt === "object" && options.insertAt.before) {
		var nextSibling = getElement(options.insertAt.before, target);
		target.insertBefore(style, nextSibling);
	} else {
		throw new Error("[Style Loader]\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top', 'bottom', or Object.\n (https://github.com/webpack-contrib/style-loader#insertat)\n");
	}
}

function removeStyleElement (style) {
	if (style.parentNode === null) return false;
	style.parentNode.removeChild(style);

	var idx = stylesInsertedAtTop.indexOf(style);
	if(idx >= 0) {
		stylesInsertedAtTop.splice(idx, 1);
	}
}

function createStyleElement (options) {
	var style = document.createElement("style");

	if(options.attrs.type === undefined) {
		options.attrs.type = "text/css";
	}

	if(options.attrs.nonce === undefined) {
		var nonce = getNonce();
		if (nonce) {
			options.attrs.nonce = nonce;
		}
	}

	addAttrs(style, options.attrs);
	insertStyleElement(options, style);

	return style;
}

function createLinkElement (options) {
	var link = document.createElement("link");

	if(options.attrs.type === undefined) {
		options.attrs.type = "text/css";
	}
	options.attrs.rel = "stylesheet";

	addAttrs(link, options.attrs);
	insertStyleElement(options, link);

	return link;
}

function addAttrs (el, attrs) {
	Object.keys(attrs).forEach(function (key) {
		el.setAttribute(key, attrs[key]);
	});
}

function getNonce() {
	if (false) {}

	return __webpack_require__.nc;
}

function addStyle (obj, options) {
	var style, update, remove, result;

	// If a transform function was defined, run it on the css
	if (options.transform && obj.css) {
	    result = typeof options.transform === 'function'
		 ? options.transform(obj.css) 
		 : options.transform.default(obj.css);

	    if (result) {
	    	// If transform returns a value, use that instead of the original css.
	    	// This allows running runtime transformations on the css.
	    	obj.css = result;
	    } else {
	    	// If the transform function returns a falsy value, don't add this css.
	    	// This allows conditional loading of css
	    	return function() {
	    		// noop
	    	};
	    }
	}

	if (options.singleton) {
		var styleIndex = singletonCounter++;

		style = singleton || (singleton = createStyleElement(options));

		update = applyToSingletonTag.bind(null, style, styleIndex, false);
		remove = applyToSingletonTag.bind(null, style, styleIndex, true);

	} else if (
		obj.sourceMap &&
		typeof URL === "function" &&
		typeof URL.createObjectURL === "function" &&
		typeof URL.revokeObjectURL === "function" &&
		typeof Blob === "function" &&
		typeof btoa === "function"
	) {
		style = createLinkElement(options);
		update = updateLink.bind(null, style, options);
		remove = function () {
			removeStyleElement(style);

			if(style.href) URL.revokeObjectURL(style.href);
		};
	} else {
		style = createStyleElement(options);
		update = applyToTag.bind(null, style);
		remove = function () {
			removeStyleElement(style);
		};
	}

	update(obj);

	return function updateStyle (newObj) {
		if (newObj) {
			if (
				newObj.css === obj.css &&
				newObj.media === obj.media &&
				newObj.sourceMap === obj.sourceMap
			) {
				return;
			}

			update(obj = newObj);
		} else {
			remove();
		}
	};
}

var replaceText = (function () {
	var textStore = [];

	return function (index, replacement) {
		textStore[index] = replacement;

		return textStore.filter(Boolean).join('\n');
	};
})();

function applyToSingletonTag (style, index, remove, obj) {
	var css = remove ? "" : obj.css;

	if (style.styleSheet) {
		style.styleSheet.cssText = replaceText(index, css);
	} else {
		var cssNode = document.createTextNode(css);
		var childNodes = style.childNodes;

		if (childNodes[index]) style.removeChild(childNodes[index]);

		if (childNodes.length) {
			style.insertBefore(cssNode, childNodes[index]);
		} else {
			style.appendChild(cssNode);
		}
	}
}

function applyToTag (style, obj) {
	var css = obj.css;
	var media = obj.media;

	if(media) {
		style.setAttribute("media", media)
	}

	if(style.styleSheet) {
		style.styleSheet.cssText = css;
	} else {
		while(style.firstChild) {
			style.removeChild(style.firstChild);
		}

		style.appendChild(document.createTextNode(css));
	}
}

function updateLink (link, options, obj) {
	var css = obj.css;
	var sourceMap = obj.sourceMap;

	/*
		If convertToAbsoluteUrls isn't defined, but sourcemaps are enabled
		and there is no publicPath defined then lets turn convertToAbsoluteUrls
		on by default.  Otherwise default to the convertToAbsoluteUrls option
		directly
	*/
	var autoFixUrls = options.convertToAbsoluteUrls === undefined && sourceMap;

	if (options.convertToAbsoluteUrls || autoFixUrls) {
		css = fixUrls(css);
	}

	if (sourceMap) {
		// http://stackoverflow.com/a/26603875
		css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */";
	}

	var blob = new Blob([css], { type: "text/css" });

	var oldSrc = link.href;

	link.href = URL.createObjectURL(blob);

	if(oldSrc) URL.revokeObjectURL(oldSrc);
}


/***/ }),

/***/ "./node_modules/style-loader/lib/urls.js":
/*!***********************************************!*\
  !*** ./node_modules/style-loader/lib/urls.js ***!
  \***********************************************/
/*! no static exports found */
/***/ (function(module, exports) {


/**
 * When source maps are enabled, `style-loader` uses a link element with a data-uri to
 * embed the css on the page. This breaks all relative urls because now they are relative to a
 * bundle instead of the current page.
 *
 * One solution is to only use full urls, but that may be impossible.
 *
 * Instead, this function "fixes" the relative urls to be absolute according to the current page location.
 *
 * A rudimentary test suite is located at `test/fixUrls.js` and can be run via the `npm test` command.
 *
 */

module.exports = function (css) {
  // get current location
  var location = typeof window !== "undefined" && window.location;

  if (!location) {
    throw new Error("fixUrls requires window.location");
  }

	// blank or null?
	if (!css || typeof css !== "string") {
	  return css;
  }

  var baseUrl = location.protocol + "//" + location.host;
  var currentDir = baseUrl + location.pathname.replace(/\/[^\/]*$/, "/");

	// convert each url(...)
	/*
	This regular expression is just a way to recursively match brackets within
	a string.

	 /url\s*\(  = Match on the word "url" with any whitespace after it and then a parens
	   (  = Start a capturing group
	     (?:  = Start a non-capturing group
	         [^)(]  = Match anything that isn't a parentheses
	         |  = OR
	         \(  = Match a start parentheses
	             (?:  = Start another non-capturing groups
	                 [^)(]+  = Match anything that isn't a parentheses
	                 |  = OR
	                 \(  = Match a start parentheses
	                     [^)(]*  = Match anything that isn't a parentheses
	                 \)  = Match a end parentheses
	             )  = End Group
              *\) = Match anything and then a close parens
          )  = Close non-capturing group
          *  = Match anything
       )  = Close capturing group
	 \)  = Match a close parens

	 /gi  = Get all matches, not the first.  Be case insensitive.
	 */
	var fixedCss = css.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi, function(fullMatch, origUrl) {
		// strip quotes (if they exist)
		var unquotedOrigUrl = origUrl
			.trim()
			.replace(/^"(.*)"$/, function(o, $1){ return $1; })
			.replace(/^'(.*)'$/, function(o, $1){ return $1; });

		// already a full url? no change
		if (/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/|\s*$)/i.test(unquotedOrigUrl)) {
		  return fullMatch;
		}

		// convert the url to a full url
		var newUrl;

		if (unquotedOrigUrl.indexOf("//") === 0) {
		  	//TODO: should we add protocol?
			newUrl = unquotedOrigUrl;
		} else if (unquotedOrigUrl.indexOf("/") === 0) {
			// path should be relative to the base url
			newUrl = baseUrl + unquotedOrigUrl; // already starts with '/'
		} else {
			// path should be relative to current directory
			newUrl = currentDir + unquotedOrigUrl.replace(/^\.\//, ""); // Strip leading './'
		}

		// send back the fixed url(...)
		return "url(" + JSON.stringify(newUrl) + ")";
	});

	// send back the fixed css
	return fixedCss;
};


/***/ })

/******/ });